/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package models.spider.request;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import play.Logger;

/**
 * 
 * @author laurent@opprecht.info
 */
public class Factory {
	
    public static class TrustAllManager implements X509TrustManager {

        private static boolean isInstalled = false;

        static void install() {
            if (isInstalled) {
                return;
            }
            TrustManager[] trustAllCerts = new TrustManager[] { new TrustAllManager() };

            SSLContext sc;
            try {
                sc = SSLContext.getInstance("SSL");
            } catch (NoSuchAlgorithmException e1) {
                Logger.error("NoSuchAlgorithmException", e1);
                return;
            }
            try {
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
            } catch (KeyManagementException e2) {
                Logger.error("KeyManagementException", e2);
                return;
            }
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            isInstalled = true;
        }

        public static HttpClient wrap(final HttpClient base) {
            try {
                SSLContext ctx = SSLContext.getInstance("TLS");
                X509TrustManager tm = new TrustAllManager();
                ctx.init(null, new TrustManager[] { tm }, null);
                SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                ClientConnectionManager ccm = base.getConnectionManager();
                SchemeRegistry sr = ccm.getSchemeRegistry();
                sr.register(new Scheme("https", 443, ssf));
                return new DefaultHttpClient(ccm, base.getParams());
            } catch (Exception ex) {
                ex.printStackTrace();
                return null;
            }
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {
        }

        @Override
        public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {
        }

    }

    public static class TrustHostNameVerifier implements X509HostnameVerifier {

        @Override
        public boolean verify(final String arg0, final SSLSession arg1) {
            return true;
        }

        @Override
        public void verify(final String host, final SSLSocket ssl) throws IOException {
            ;
        }

        @Override
        public void verify(final String host, final X509Certificate cert) throws SSLException {
            ;
        }

        @Override
        public void verify(final String host, final String[] cns, final String[] subjectAlts) throws SSLException {
            ;
        }

    }
    
    static {
        TrustAllManager.install();
    }
	
	protected static volatile HttpClient client = null;

    public Request create(final String url) {
        if (StringUtils.isEmpty(url)) {
            return Request.EMPTY;
        }

        try {
            URL u = new URL(url);
            if(client==null) {
            	PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
                cm.setMaxTotal(100);
                cm.setDefaultMaxPerRoute(100);
                DefaultHttpClient httpClient = new DefaultHttpClient(cm);
                httpClient.setRedirectStrategy(new LaxRedirectStrategy());
                httpClient.getParams().setParameter("http.tcp.nodelay", true);
                httpClient.getParams().setParameter("http.connection.stalecheck", false);
                HttpParams params = httpClient.getParams();
                HttpConnectionParams.setConnectionTimeout(params, 120 * 1000);
                client = TrustAllManager.wrap(httpClient);
            }
            Request result = new Request(u,client);
            return result;
        } catch (MalformedURLException ex) {
            Logger.warn("invalid url " + url, ex);
            return Request.EMPTY;
        }
    }
}
